<template>
  <el-form
    ref="ruleFormRef"
    inline
    :rules="rules"
    label-width="100px"
    :model="model"
    v-bind="formAttrs"
    :validate-on-rule-change="false"
    @submit.prevent
  >
    <el-form-item v-for="item of displayOptions" :key="item.prop" :prop="item.prop" :label="setDisplayLabel(item.label)">
      <template v-if="item.type === 'cascader'">
        <!-- cascader 有默认插槽无法兼容 -->
        <component
          :is="`el-${item.type}`"
          v-bind="item.attrs"
          :style="setItemStyle(item)"
          v-model="model[item.prop]"
          :placeholder="setPlaceholder(item)"
          @change="allFun(item, 'changeMethod')"
          @input="allFun(item, 'inputMethod')"
        >
        </component>
      </template>
      <component
        v-else
        :is="`el-${item.type}`"
        v-bind="item.attrs"
        :style="setItemStyle(item)"
        v-model="model[item.prop]"
        :placeholder="setPlaceholder(item)"
        @change="allFun(item, 'changeMethod')"
        @input="allFun(item, 'inputMethod')"
      >
        <template v-if="item?.children">
          <component
            :is="`el-${child.type}`"
            v-for="child in item.children"
            :key="child.label"
            :value="child.value"
            :label="child.label"
          />
        </template>
      </component>
    </el-form-item>

    <div class="flx-justify-end">
      <ElButton @click="cancel">{{ _transitionLanguages("button", "cancel") }}</ElButton>
      <ElButton type="primary" @click="submitForm(ruleFormRef)" :loading="loading">
        {{ _transitionLanguages("button", "save") }}
      </ElButton>
    </div>
  </el-form>
</template>
<script setup lang="ts" name="proForm">
import { optionsProps, FormProps } from "@/components/ProForm/interface";

import type { FormInstance } from "element-plus";
import { onBeforeMount, computed, ref, CSSProperties } from "vue";

// 深拷贝
import { cloneDeep } from "lodash";
import { useGlobalStore } from "@/stores/modules/global";
import { FormWIdthEnum } from "@/enums";
export interface ProFormProps {
  options: optionsProps[];
  visible: boolean;
  formAttrs?: FormProps;
  formCols?: number;
}
const props = withDefaults(defineProps<ProFormProps>(), {
  options: () => [],
  formCols: 2,
  visible: false
});

const $emit = defineEmits(["getModel", "cancel", "update:visible", "validateForm"]);

const globalStore = useGlobalStore();
const ruleFormRef = ref<FormInstance>();

// 语言转换
const _transitionLanguages = (v: string, l: string): string => {
  return transitionLanguages(v, l);
};

const loading = computed(() => globalStore.formLoading);

// 需要显示的表单
const displayOptions = computed(() => props.options.filter(op => !op.hide));

// 验证规则
const rules = computed(() => {
  let r: any = {};
  for (let op of props.options) {
    let rules = cloneDeep(op?.rules || []);
    for (let rs of rules) {
      if (rs.message === op.label) {
        rs.message = transitionLanguages("table", op.label) + isSpacing() + transitionLanguages("rules", "canNotBeEmpty");
      }
    }
    r[op["prop"]] = rules || [];
  }
  return r;
});

let model = ref();

onBeforeMount(() => {
  initForm();
  document.onkeydown = keyupSubmit;
});

const keyupSubmit = (e: KeyboardEvent) => {
  if (e.key === "Enter") {
    if (!props.visible) {
      return;
    }
    submitForm(ruleFormRef.value);
  }
};

const initForm = () => {
  model.value = {};
  for (let op of props.options) {
    const { defaultValue, prop } = op;
    model.value[prop] = defaultValue;
  }

  // 将字段给到父级 方便后续字段修改
  $emit("getModel", model.value);
};

const cancel = () => {
  $emit("update:visible", false);
  $emit("cancel", false);
};

const submitForm = async (formEl: FormInstance | undefined) => {
  return new Promise(async resolve => {
    if (!formEl) return;
    await formEl.validate((valid, fields) => {
      if (valid) {
        $emit("validateForm", model.value);
        globalStore.formLoading = true;
        resolve(valid);
      } else {
        console.log(fields);
        // reject(fields);
      }
    });
  });
};

const allFun = (item: optionsProps, fun: "changeMethod" | "inputMethod") => {
  if (typeof item[fun] === "function") {
    switch (fun) {
      case "inputMethod":
        item.inputMethod && item.inputMethod(model);
      default:
        item.changeMethod && item.changeMethod(model);
        break;
    }
  }
};

// 设置默认占位符
const setPlaceholder = (item: optionsProps) => {
  let placeholder = item.attrs?.placeholder;

  // 选择类型字段
  const selectTypes = ["select", "date"];

  const { type, label } = item;

  // 输入框 还是 选择框
  const useType = selectTypes.includes(type) ? "select" : "input";
  const p = !placeholder
    ? selectTransitionLanguages(`table`, label, useType)
    : selectTransitionLanguages("placeholder", item.attrs?.placeholder || "", useType);

  return p;
};

// 设置显示的标签
const setDisplayLabel = (label: string) => {
  return transitionLanguages("table", label);
};

// 设置默认 form-item 宽度
const setItemStyle = (item: optionsProps) => {
  const { style } = item.attrs || {};

  let s: CSSProperties = {};

  // 有自定义样式使用自定义样式
  if (style) {
    s = style;
  }

  // 如果没有设置宽度设置默认form-item 宽度
  if (!s.width) {
    const { width } = style || {};
    s.width = width || FormWIdthEnum.itemCol1;
  }

  return s;
};

defineExpose({
  submitForm
});
</script>
